package checker

import (
	"math/big"
	"mi/compiler/ast"
	"mi/compiler/binder"
)

type nodeCheckFlags = int
const (
	typeChecked       nodeCheckFlags = 1 << iota // Node has been type checked
	superInstance                                // Instance 'super' reference
	superStatic                                  // Static 'super' reference
	contextChecked                               // Contextual types have been assigned
)

type nodeLinks struct {
	resolvedType                         Type                                         // Cached type of type node
	resolvedFlowType                     Type                                         // Cache resolve flow type
	resolvedFlowTypeSource               int                                          // Source of tag value, not yet implemented
	resolvedSignature                    *Signature                                   // Cached signature of signature node or call expression
	resolvedCandidates                   []*Signature                                 // Cached Candidate signatures
	resolvedSymbol                       *binder.Symbol                               // Cached name resolution result
	accessibilityDefferCheckHandle       func(signature *Signature) bool 			  // Check signature accessibility
	baseTypeHasAvailableConstructor      *bool										  // Class base type has available constructor
	flags                                nodeCheckFlags                               // Set of Flags specific to Node
	isIllegalTypeReferenceInConstraint   *bool                                        // Is type reference in constraint refers to the type parameter from the same list
	isVisible                            *bool                                        // Is this node visible
	hasReportedStatementInAmbientContext *bool
	localModuleName                      string              // Local name for module instance
	hasSuperCall                         *bool               // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
	superCall                            *ast.CallExpression // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
	literalValue                         *big.Float          // Form number like literal (e.g int long float double)
	resolvedImportSymbols                []*binder.Symbol    // Form session import declaration
	contextualType                       Type                // Expression
}

type checkFlags int
const (
	instantiated = 1 << iota // Instantiated symbol
	readOnly                 // Readonly transient symbol
)

type annotationFlags int
const (
	noAllow   annotationFlags = 0
	typeAllow annotationFlags = 1 << iota
	fieldAllow
	methodAllow
	parameterAllow
	constructorAllow
	localVariableAllow
	annotationTypeAllow
	packageAllow
	typeParameterAllow
	typeUseAllow
	allAllow annotationFlags = 1 << 16 - 1
)

type symbolLinks struct {
	target                     *binder.Symbol   // Resolved (non-alias) target of an alias
	mappedSymbol               *binder.Symbol   // Resolved alias symbol mapper symbol
	tpe                        Type             // Type of value Symbol
	declarationType            Type             // Type of class, interface, enum, or type parameter
	typeParameters             []*typeParameter // Type parameters of type alias (nil if non-generic)
	instantiations             map[string]Type  // Instantiations of generic type alias (nil if non-generic)
	mapper                     *TypeMapper      // Type mapper for instantiation alias
	referenced                 bool             // True if alias Symbol has been referenced as a value
	isFunctionalInterface      *bool            // Interface Has @FunctionalInterface
	methodName                 *string          // Functional interface method name
	annotationTargetFlags      *annotationFlags // Form java.lang.annotation
	path                       *string          // Type path (e.g java.lang.Annotation.ElementType)
	inheritedSignatures        map[*binder.Symbol][]*Signature
	missingImplementSignatures map[*binder.Symbol][]*Signature
	checkFlags                 checkFlags	 	// TransientSymbol
}
